using System;
using System.Collections.Generic;
using System.Text;
using ECommerce.Library.DataStructure;
using ECommerce.Library.ECommerce;
using Entity;
using ECommerce.Library;
using log4net;
using System.IO;
using System.Web;
using System.Data.SqlTypes;
using eShop.Model;
using eShop.DataAccess;
using eShop.Business;

namespace AutoGear.BLL
{
    public class Product : IProduct
    {
        #region Product Constractor

        public Product() { }

        public Product
        (
            int productId,
            string productName,
             string productName2,
            string productDescription,
            string productImageUrl,
            string displayOrder,
            int visitCount,
            double oldPrice,
            double retailPrice,
            double additionalPrice,
            string additionalPriceDesc,
            string recipies,
            string additionalinfo,
            DateTime createDate,
            string itemNumber,
            bool isFeatured,
            bool isFreeShipping,
            bool isNewArrival,
            bool isActive,
            bool isDeleted,
            bool isClearenceItem,
            string productUrl,
            double productPrice,
            double currentCost,
            double standardCost,
            bool isSpecial,
            Manufacturer productBrand,
            Category productCategory,
            ReadOnlyCustomCollection<ProductStock> stocks
        )
        {
            _productId = productId;
            _productName = productName;
            _productName2 = productName2;
            _productDescription = productDescription;
            _productImageUrl = productImageUrl;
            _displayOrder = displayOrder;
            _visitCount = visitCount;
            _oldPrice = oldPrice;
            _retailPrice = retailPrice;
            _additionalPrice = additionalPrice;
            _additionalPriceDesc = additionalPriceDesc;
            _recipies = recipies;
            _additionalinfo = additionalinfo;
            _createDate = createDate;
            _itemNumber = itemNumber;
            _isFeatured = isFeatured;
            _isFreeShipping = isFreeShipping;
            _isNewArrival = isNewArrival;
            _isActive = isActive;
            _isDeleted = isDeleted;
            _isClearenceItem = isClearenceItem;
            _productUrl = productUrl;
            _productPrice = productPrice;
            _productBrand = productBrand;
            _productCategory = productCategory;
            _currentCost = currentCost;
            //_standardCost = standardCost;
            _standardCost = productPrice;
            _isSpecial = isSpecial;
            _stocks = new ReadWriteCustomCollection<ProductStock>(stocks);
        }

        public Product
        (
            int productId,
            string productName,
              string productName2,
            string productDescription,
            string productImageUrl,
            string displayOrder,
            int visitCount,
            double oldPrice,
            double retailPrice,
            double additionalPrice,
            string additionalPriceDesc,
            string recipies,
            string additionalinfo,
            DateTime createDate,
            string itemNumber,
            bool isFeatured,
            bool isFreeShipping,
            bool isNewArrival,
            bool isActive,
            bool isDeleted,
            bool isClearenceItem,
            string productUrl,
            double productPrice,
            double currentCost,
            double standardCost,
            bool isSpecial,
            Manufacturer productBrand,
            Category productCategory,
            List<ProductStock> stocks
        )
        {
            _productId = productId;
            _productName = productName;
            _productName2 = productName2;
            _productDescription = productDescription;
            _productImageUrl = productImageUrl;
            _displayOrder = displayOrder;
            _visitCount = visitCount;
            _oldPrice = oldPrice;
            _retailPrice = retailPrice;
            _additionalPrice = additionalPrice;
            _additionalPriceDesc = additionalPriceDesc;
            _recipies = recipies;
            _additionalinfo = additionalinfo;
            _createDate = createDate;
            _itemNumber = itemNumber;
            _isFeatured = isFeatured;
            _isFreeShipping = isFreeShipping;
            _isNewArrival = isNewArrival;
            _isActive = isActive;
            _isDeleted = isDeleted;
            _isClearenceItem = isClearenceItem;
            _productUrl = productUrl;
            _productPrice = productPrice;
            _currentCost = currentCost;
           // _standardCost = standardCost;
            _standardCost = productPrice;
            _isSpecial = isSpecial;
            _productBrand = productBrand;
            _productCategory = productCategory;
            _stocks = new ReadWriteCustomCollection<ProductStock>(stocks);
        }

        public Product
        (
            TblProduct productData
        )
        {
            if (productData != null)
            {
                this._productId = productData.ProductId;
                this._productName = productData.ProductName;
                this._productName2 = productData.ProductName2;
                this._productDescription = productData.ProductDescription;
                this._productImageUrl = productData.ProductImageUrl;
                this._displayOrder = productData.DisplayOrder;
                this._visitCount = productData.VisitCount;
                this._oldPrice = Convert.ToDouble(productData.OldPrice);
                this._retailPrice = Convert.ToDouble(productData.RetailPrice);
                this._additionalPrice = Convert.ToDouble(productData.AdditionalPrice);
                this._additionalPriceDesc = productData.AdditionalPriceDesc;
                this._recipies = productData.Recipies;
                this._additionalinfo = productData.AdditionalInfo;
                this._createDate = productData.CreateDate;
                this._itemNumber = productData.ItemNumber;
                this._isFeatured = productData.IsFeatured;
                this._isFreeShipping = productData.IsFreeShipping;
                this._isNewArrival = productData.IsNewArrival;
                this._isActive = productData.IsActive;
                this._isDeleted = productData.IsDeleted;
                this._isClearenceItem = productData.IsClearenceItem;
                this._productPrice = Convert.ToDouble(productData.ProductPrice);
                this._currentCost = Convert.ToDouble(productData.CurrentCost);
               this._standardCost = Convert.ToDouble(productData.StandardCost);
               // this._standardCost = Convert.ToDouble(productData.ProductPrice);
                this._isSpecial = Convert.ToBoolean(productData.IsSpecial);
                this._productUrl = productData.ProductUrl;
                this._productBrand = ManufacturerManager.GetById(productData.BrandId);
                this._productCategory = CategoryManager.Load(productData.CategoryId);
                ECommerce.DAL.CustomCollection<TblProductStock> productStockData = TblProductStockExtended.GetProductStockByProductId(this._productId);
                this._stocks = ProductStock.LoadFromCustomCollection(productStockData);
            }
        }

        #endregion

        private int _productId;
        public int ProductId
        {
            get { return _productId; }
        }

        private bool _isProductNameChanged;
        public bool IsProductNameChanged
        {
            get { return this._isProductNameChanged; }
        }

        private string _productName;
        public string ProductName
        {
            get { return _productName; }
            set { _productName = value; _isProductNameChanged = true; }
        }
        private string _productName2;
        public string ProductName2
        {
            get { return _productName2; }
            set { _productName2 = value; _isProductNameChanged = true; }
        }

        private string _productDescription;
        public string ProductDescription
        {
            get { return this._productDescription; }
            set { this._productDescription = value; }
        }

        private string _productImageUrl;
        public string ProductImageUrl
        {
            get { return _productImageUrl; }
            set { _productImageUrl = value; }
        }

        public string ProductImageSmallThumbnail
        {
            get { return _productImageUrl.Replace("list", "smallthumb"); }
        }

        public string ProductImageLargeThumbnail
        {
            get { return _productImageUrl.Replace("list", "largethumb"); }
        }

        public string ProductImageDetailSize
        {
            get { return _productImageUrl.Replace("list", "detail"); }
        }

        public string ProductImageMaxSize
        {
            get { return _productImageUrl.Replace("list", "max"); }
        }

        private string _displayOrder;
        public string DisplayOrder
        {
            get { return _displayOrder; }
            set { _displayOrder = value; }
        }

        private int _visitCount = 0;
        public int VisitCount
        {
            get { return _visitCount; }
            set { _visitCount = value; }
        }

        private string _productUrl;
        public string ProductUrl
        {
            get { return _productUrl; }
        }

        private double _productPrice;
        public double ProductPrice
        {
            get 
            {
                return _productPrice; // +(_productPrice * (Brand.ProductPricePercentage / 100d));
            }
            set { _productPrice = value; }
        }
        public double ProductActualPrice
        {
            get { return _productPrice; }
            set { _productPrice = value; }
        }

        private double _oldPrice;
        public double OldPrice
        {
            get { return this._oldPrice; }
            set { this._oldPrice = value; }
        }

        private double _retailPrice;
        public double RetailPrice
        {
            get { return this._retailPrice; }
            set { this._retailPrice = value; }
        }
        private double _additionalPrice;
        public double AdditionalPrice 
        {
            get { return this._additionalPrice; }
            set { this._additionalPrice = value; }
        }
        private string _additionalPriceDesc;
        public string AdditionalPriceDesc 
        {
            get { return this._additionalPriceDesc; }
            set { this._additionalPriceDesc = value; }
        }
        private string _recipies;
        public string Recipies 
        {
            get { return this._recipies; }
            set {this._recipies=value ;}
        }
        private string _additionalinfo;
        public string AdditionalInfo
        {
            get { return this._additionalinfo; }
            set { this._additionalinfo = value; }
        }
        private double _currentCost;
        public double CurrentCost
        {
            get { return this._currentCost; }
            set { this._currentCost = value; }
        }
        private double _standardCost;
        public double StandardCost
        {
            get { return this._standardCost; }
            set { this._standardCost = value; }
        }

        private bool _isSpecial;
        public bool IsSpecial
        {
            get { return this._isSpecial; }
            set { this._isSpecial = value; }
        }

        private DateTime _createDate;
        public DateTime CreateDate
        {
            get
            {
                if (_createDate < SqlDateTime.MinValue.Value)
                    return SqlDateTime.MinValue.Value;
                return this._createDate;
            }
            set { this._createDate = value; }
        }

        private Manufacturer _productBrand;
        public Manufacturer Brand
        {
            get { return this._productBrand; }
            set { this._productBrand = value; }
        }

        private Category _productCategory;
        public Category Category
        {
            get { return this._productCategory; }
            set { this._productCategory = value; }
        }

        private ReadWriteCustomCollection<ProductStock> _stocks;
        public ReadOnlyCustomCollection<ProductStock> Stocks
        {
            get { return this._stocks.ReadOnlyClone(); }
        }

        public static ReadWriteCustomCollection<Product> Search(string keyword, string itemNumber,
            SearchType searchType)
        {
            if (searchType == SearchType.SearchByItemNumberAndKeyword)
            {
                if (string.IsNullOrEmpty(keyword))
                    keyword = "%";
                if (string.IsNullOrEmpty(itemNumber))
                    itemNumber = "%";

                ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetProductByKeywordAndItemNumber(keyword, itemNumber);
                return LoadFromCustomCollection(productData);
            }
            else
                return null;
        }

        public static ReadWriteCustomCollection<Product> SearchByBothName(int currentPageIndex, int pageSize, string keyword, string itemNumber, SearchType searchType)
        {
            if (searchType == SearchType.SearchByItemNumberAndKeyword)
            {
                if (string.IsNullOrEmpty(keyword))
                    keyword = "%";
                if (string.IsNullOrEmpty(itemNumber))
                    itemNumber = "%";

                ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetProductByBothName((currentPageIndex - 1) * pageSize, pageSize, keyword, itemNumber);
                return LoadFromCustomCollection(productData);
            }
            else
                return null;
        }

        public static int SearchByBothNameCount(string keyword, string itemNumber, SearchType searchType)
        {
            if (searchType == SearchType.SearchByItemNumberAndKeyword)
            {
                if (string.IsNullOrEmpty(keyword))
                    keyword = "%";
                if (string.IsNullOrEmpty(itemNumber))
                    itemNumber = "%";

                return TblProductExtended.GetProductByBothNameCount(keyword, itemNumber);
            }
            else
                return 0;
        }

        public static ReadWriteCustomCollection<Product> SearchByPrice(string minPrice, string maxPrice)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetProductByPrice(minPrice, maxPrice);
            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> SearchByExactProductName(string productName)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetProductByExactName(productName);
            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> SearchByPrice(string minPrice, string maxPrice, string orderby, int currentPageIndex, int pageSize)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetProductByPrice(minPrice, maxPrice, orderby, currentPageIndex, pageSize);
            return LoadFromCustomCollection(productData);
        }

        public void AddStock(ProductStock stock)
        {
            this._stocks.Add(stock);
            ProductStock.Create(stock);
        }

        public void RemoveStock(ProductStock stock)
        {
            foreach (ProductStock productStock in Stocks)
            {
                if (productStock.StockId == stock.StockId)
                {
                    this._stocks.Remove(stock);
                    TblProductStock.DeleteTblProductStock(stock.StockId);
                    break;
                }
            }
        }

        public void ReduceStock(int qty)
        {

            ECommerce.DAL.CustomCollection<TblProductStock> Stocks = TblProductStockExtended.GetProductStockByProductId(this.ProductId);
            if (Stocks.Count > 0)
            {
                Stocks[0].StockAmount = Stocks[0].StockAmount - qty;
                TblProductStock.UpdateTblProductStock(Stocks[0]);
            }
        }

        public static ReadWriteCustomCollection<Product> FeaturedProducts(int howMany)
        {
            ReadWriteCustomCollection<Product> featuredProduct = new ReadWriteCustomCollection<Product>();
            try
            {
                ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetFeaturedProducts(howMany);
                featuredProduct = LoadFromCustomCollection(productData);
                return featuredProduct;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static ReadWriteCustomCollection<Product> GetAllTblPartnerProductByPartnerName(string partnerName)
        {
            ReadWriteCustomCollection<Product> featuredProduct = new ReadWriteCustomCollection<Product>();
            try
            {
                ECommerce.DAL.CustomCollection<TblProduct> productData = TblPartnerProduct.GetAllTblPartnerProductByPartnerName(partnerName);
                featuredProduct = LoadFromCustomCollection(productData);
                return featuredProduct;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static ReadWriteCustomCollection<Product> GetAllFeaturedProductByPartnerName(string partnerName)
        {
            ReadWriteCustomCollection<Product> featuredProduct = new ReadWriteCustomCollection<Product>();
            try
            {
                ECommerce.DAL.CustomCollection<TblProduct> productData = TblPartnerProduct.GetAllFeaturedProductByPartnerName(partnerName);
                featuredProduct = LoadFromCustomCollection(productData);
                return featuredProduct;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static ReadWriteCustomCollection<Product> GetAllTblPartnerProductByPartnerName(string partnerName,string categoryName)
        {
            ReadWriteCustomCollection<Product> featuredProduct = new ReadWriteCustomCollection<Product>();
            try
            {
                ECommerce.DAL.CustomCollection<TblProduct> productData = TblPartnerProduct.GetAllTblPartnerProductByPartnerName(partnerName, categoryName);
                featuredProduct = LoadFromCustomCollection(productData);
                return featuredProduct;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static ReadWriteCustomCollection<Product> RelatedProducts(int howMany, int categoryId,int productId)
        {
            ReadWriteCustomCollection<Product> relatedProduct = new ReadWriteCustomCollection<Product>();
            try
            {
                ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetRelatedProducts(howMany, categoryId, productId);
                relatedProduct = LoadFromCustomCollection(productData);
                return relatedProduct;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static ReadWriteCustomCollection<Product> FeaturedProducts(int currentPageIndex, int pageSize)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;
            productData = TblProductExtended.GetActiveFeaturedProducts(currentPageIndex, pageSize);
            return LoadFromCustomCollection(productData);
        }

        public static int FeatureProductCount()
        {
            int count = 0;

            count = TblProductExtended.GetActiveFeaturedProductsCount();
            
            return count;
        }


        #region IProduct Members

        private string _itemNumber;
        public string ItemNumber
        {
            get { return this._itemNumber; }
            set { this._itemNumber = value; }
        }

        private bool _isFeatured;
        public bool IsFeatured
        {
            get { return this._isFeatured; }
            set { this._isFeatured = value; }
        }

        private bool _isFreeShipping;
        public bool IsFreeShipping
        {
            get { return this._isFreeShipping; }
            set { this._isFreeShipping = value; }
        }

        private bool _isNewArrival;
        public bool IsNewArrival
        {
            get { return this._isNewArrival; }
            set { this._isNewArrival = value; }
        }

        private bool _isActive;
        public bool IsActive
        {
            get { return this._isActive; }
            set { this._isActive = value; }
        }

        private bool _isDeleted;
        public bool IsDeleted
        {
            get { return this._isDeleted; }
            set { this._isDeleted = value; }
        }

        private bool _isClearenceItem;
        public bool IsClearenceItem
        {
            get { return this._isClearenceItem; }
            set { this._isClearenceItem = value; }
        }

        #endregion

        public static ReadWriteCustomCollection<Product> ProductByManufacturer(int brandId, int currentPageIndex, int pageSize, DataState dataState)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;

            if (dataState == DataState.Active)
            {
                productData = TblProductExtended.GetActiveProductsByBrand(brandId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.NonDeleted)
            {
                productData = TblProductExtended.GetNonDeletedProductsByBrand(brandId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.All)
            {
                productData = TblProductExtended.GetAllProductsByBrand(brandId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> ProductByCategory(int categoryId, string orderby, int currentPageIndex, int pageSize, DataState dataState)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;

            if (dataState == DataState.Active)
            {
                productData = TblProductExtended.GetActiveProductsByCategory(orderby, categoryId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.NonDeleted)
            {
                productData = TblProductExtended.GetNonDeletedProductsByCategory(categoryId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.All)
            {
                productData = TblProductExtended.GetAllProductsByCategory(categoryId, (currentPageIndex - 1) * pageSize, pageSize);
            }
            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> Products(int currentPageIndex, int pageSize, DataState dataState)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;

            if (dataState == DataState.Active)
            {
                productData = TblProductExtended.GetActiveProducts((currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.NonDeleted)
            {
                productData = TblProductExtended.GetNonDeletedProducts((currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.All)
            {
                productData = TblProduct.GetAllTblProductPaged("ProductName", (currentPageIndex - 1) * pageSize, pageSize);
            }
            return LoadFromCustomCollection(productData);
        }
        public static ReadWriteCustomCollection<Product> SpecialProducts(int currentPageIndex, int pageSize, DataState dataState)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;

            if (dataState == DataState.Active)
            {
                productData = TblProductExtended.GetActiveSpecialProducts((currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.NonDeleted)
            {
                productData = TblProductExtended.GetNonDeletedProducts((currentPageIndex - 1) * pageSize, pageSize);
            }
            else if (dataState == DataState.All)
            {
                productData = TblProduct.GetAllTblProductPaged("ProductName", (currentPageIndex - 1) * pageSize, pageSize);
            }
            return LoadFromCustomCollection(productData);
        }

        public static int ProductCountByCategory(int categoryId, DataState dataState)
        {
            int count = 0;

            if (dataState == DataState.Active)
            {
                count = TblProductExtended.GetActiveProductsCountByCategory(categoryId);
            }
            else if (dataState == DataState.NonDeleted)
            {
                count = TblProductExtended.GetNonDeletedProductsCountByCategory(categoryId);
            }
            else if (dataState == DataState.All)
            {
                count = TblProductExtended.GetAllProductsCountByCategory(categoryId);
            }
            return count;
        }

        public static int ProductCountByManufacturer(int brandId, DataState dataState)
        {
            int count = 0;

            if (dataState == DataState.Active)
            {
                count = TblProductExtended.GetActiveProductsCountByBrand(brandId);
            }
            else if (dataState == DataState.NonDeleted)
            {
                count = TblProductExtended.GetNonDeletedProductsCountByBrand(brandId);
            }
            else if (dataState == DataState.All)
            {
                count = TblProductExtended.GetAllProductsCountByBrand(brandId);
            }
            return count;
        }

        public static int ProductCount(DataState dataState)
        {
            int count = 0;

            if (dataState == DataState.Active)
            {
                count = TblProductExtended.GetActiveProductsCount();
            }
            else if (dataState == DataState.NonDeleted)
            {
                count = TblProductExtended.GetNonDeletedProductsCount();
            }
            else if (dataState == DataState.All)
            {
                count = TblProduct.GetAllTblProductPagedCount("", 0, 0);
            }
            return count;
        }

        private static ReadWriteCustomCollection<Product> LoadFromCustomCollection(ECommerce.DAL.CustomCollection<TblProduct> productData)
        {
            ReadWriteCustomCollection<Product> result = new ReadWriteCustomCollection<Product>();
            if (productData != null)
            {
                if (productData.Count > 0)
                {
                    for (int i = 0; i < productData.Count; i++)
                    {
                        result.Add(new Product(productData[i]));
                    }
                }
            }

            return result;
        }

        public static Product Load(string prodPath, string supplierName)
        {
            try
            {
                prodPath = "~/" + prodPath;
                TblProduct productData = TblProduct.GetTblProductByProductPath(prodPath, supplierName);
                Manufacturer brandData = null;
                Category categoryData = null;

                if (productData != null && productData.BrandId >0)
                    brandData = ManufacturerManager.GetById(productData.BrandId);
                if (productData != null)
                    categoryData = CategoryManager.GetById(productData.CategoryId);

                Product product = new Product(productData);
                if (brandData != null)
                    product.Brand = brandData;
                if (categoryData != null)
                    product.Category = categoryData;

                ECommerce.DAL.CustomCollection<TblProductStock> productStockData = TblProductStockExtended.GetProductStockByProductId(product.ProductId);
                ReadWriteCustomCollection<ProductStock> stocks = ProductStock.LoadFromCustomCollection(productStockData);
                product._stocks = stocks;
                return product;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        public static Product Load(string prodPath)
        {
            try
            {
                prodPath = "~/" + prodPath;
                TblProduct productData = TblProduct.GetTblProductByProductPath(prodPath);
                Manufacturer brandData = null;
                Category categoryData = null;

                if (productData != null && productData.BrandId >0)
                    brandData = ManufacturerManager.GetById(productData.BrandId);
                if (productData != null)
                    categoryData = CategoryManager.GetById(productData.CategoryId);

                Product product = new Product(productData);
                if (brandData != null)
                    product.Brand = brandData;
                if (categoryData != null)
                    product.Category = categoryData;

                ECommerce.DAL.CustomCollection<TblProductStock> productStockData = TblProductStockExtended.GetProductStockByProductId(product.ProductId);
                ReadWriteCustomCollection<ProductStock> stocks = ProductStock.LoadFromCustomCollection(productStockData);
                product._stocks = stocks;
                return product;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public static Product Load(int productId,string supplierName)
        {
            try
            {
                TblProduct productData = TblPartnerProduct.GetTblPartnerProductByPartnerName(supplierName, productId);
                Manufacturer brandData = null;
                Category categoryData = null;

                if (productData != null)
                {
                    //brandData = TblProductBrand.(productData.p);
                    brandData = ManufacturerDAO.GetTblProductBrandByProductBrandUrl(supplierName);
                }
                if (productData != null)
                    categoryData = CategoryManager.GetById(productData.CategoryId);

                Product product = new Product(productData);
                if (brandData != null)
                    product.Brand = brandData;
                if (categoryData != null)
                    product.Category = categoryData;

                ECommerce.DAL.CustomCollection<TblProductStock> productStockData = TblProductStockExtended.GetProductStockByProductId(product.ProductId);
                ReadWriteCustomCollection<ProductStock> stocks = ProductStock.LoadFromCustomCollection(productStockData);
                product._stocks = stocks;
                return product;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public static Product Load(int productId)
        {
            try
            {
                TblProduct productData = TblProduct.GetTblProductByProductId(productId);
                Manufacturer brandData = null;
                Category categoryData = null;

                if (productData != null && productData.BrandId >0)
                    brandData = ManufacturerManager.GetById(productData.BrandId);
                if (productData != null)
                    categoryData = CategoryManager.GetById(productData.CategoryId);

                Product product = new Product(productData);
                if(brandData!=null)
                product.Brand = brandData;
                if(categoryData!=null)
                product.Category = categoryData;

                ECommerce.DAL.CustomCollection<TblProductStock> productStockData = TblProductStockExtended.GetProductStockByProductId(product.ProductId);
                ReadWriteCustomCollection<ProductStock> stocks = ProductStock.LoadFromCustomCollection(productStockData);
                product._stocks = stocks;
                return product;
            }
            catch (Exception ex)
            {
                return null;
            }

        }

        public static Product CreateProduct(string name, string name2, string description, string tempImageFolder,
           string categoryId, string displayOrder, string price,double retailprice, double currentCost, double additionalPrice, string additionalPriceDesc, string recipies, string additionalinfo,
           double standardCost, bool isSpecial, string itemNumber,
           bool featuredListing, bool active, List<ProductStock> stocks)
        {
            try
            {
                name = Security.BindStringInput(name, SecurityLevel.Zero);
                name2 = Security.BindStringInput(name2, SecurityLevel.Zero);
                description = Security.BindStringInput(description, SecurityLevel.Zero);
                tempImageFolder = Security.BindStringInput(tempImageFolder, SecurityLevel.Zero);
                categoryId = Security.BindStringInput(categoryId, SecurityLevel.Zero);
                
                displayOrder = Security.BindStringInput(displayOrder, SecurityLevel.Zero);
                price = Security.BindStringInput(price, SecurityLevel.Zero);
                itemNumber = Security.BindStringInput(itemNumber, SecurityLevel.Zero);

                recipies = Security.BindStringInput(recipies, SecurityLevel.Zero);
                additionalinfo = Security.BindStringInput(additionalinfo, SecurityLevel.Zero);


                if (TblProductExtended.CountItemNumber(itemNumber) > 0)
                    throw new DuplicateException(AutoGearCommonMessage.DuplicateProductItemNumber);

                int categoryIdValue = int.Parse(categoryId);
                int brandIdValue = 0;
                double priceValue = double.Parse(price);

                Category category = CategoryManager.Load(categoryIdValue);
                if (category.SubCategoryCount > 0)
                    throw new InvalidOperationException(AutoGearCommonMessage.InvalidCategoryForProductAddition);

                int productId = TblProduct.CreateNewTblProduct(name, name2, description, string.Empty,
                     displayOrder, 0, string.Empty, Convert.ToDecimal(priceValue),
                     Convert.ToDecimal(priceValue), Convert.ToDecimal(retailprice), Convert.ToDecimal(additionalPrice), additionalPriceDesc, recipies, additionalinfo, DateTime.Now, itemNumber,
                     featuredListing, false, false, active, false, false, 0, categoryIdValue,
                     Convert.ToDecimal(currentCost), Convert.ToDecimal(standardCost), isSpecial);

                foreach (ProductStock stock in stocks)
                {
                    stock.ProductId = productId;
                    ProductStock.Create(stock);
                }

                Product newProduct = new Product(productId, name, name2, description, string.Empty, displayOrder, 0, priceValue,
                     retailprice, additionalPrice, additionalPriceDesc, recipies, additionalinfo, DateTime.Now, itemNumber, featuredListing, false, false, active, false, false,
                     string.Empty, priceValue, currentCost, standardCost, isSpecial, ManufacturerManager.GetById(brandIdValue), category, stocks);

                try
                {
                    newProduct = ProductFileAccessUtility.CreateProductFiles(newProduct, tempImageFolder);
                }
                catch (Exception ex)
                {
                    TblProduct.DeleteTblProduct(newProduct.ProductId);
                    throw ex;
                }
                TblProduct.UpdateTblProduct(newProduct.ProductId, newProduct.ProductName, newProduct.ProductName2, newProduct.ProductDescription,
                    newProduct.ProductImageUrl, newProduct.DisplayOrder, newProduct.VisitCount, newProduct.ProductUrl,
                    Convert.ToDecimal(newProduct.ProductActualPrice), Convert.ToDecimal(newProduct.OldPrice), Convert.ToDecimal(newProduct.RetailPrice), Convert.ToDecimal(newProduct.AdditionalPrice), newProduct.AdditionalPriceDesc, newProduct.Recipies, newProduct.AdditionalInfo, newProduct.CreateDate,
                    newProduct.ItemNumber, newProduct.IsFeatured, newProduct.IsFreeShipping, newProduct.IsNewArrival,
                    newProduct.IsActive, newProduct.IsDeleted, newProduct.IsClearenceItem, 0,
                    newProduct.Category.CategoryId, Convert.ToDecimal(currentCost), Convert.ToDecimal(standardCost), isSpecial);


                return newProduct;
            }
            catch (Exception ex)
            {
                // Setting log information about the exception
                StringBuilder logText = new StringBuilder("Create caused server error: Parameters( ");
                logText = logText.Append("name -> ").Append(name);
                logText = logText.Append("description -> ").Append(description);
                logText = logText.Append("tempImageFolder -> ").Append(tempImageFolder);
                logText = logText.Append("categoryId -> ").Append(categoryId);
                logText = logText.Append("brandId -> ").Append(-1);
                logText = logText.Append("displayOrder -> ").Append(displayOrder);
                logText = logText.Append("price -> ").Append(price);
                logText = logText.Append("itemNumber -> ").Append(itemNumber);
                logText = logText.Append("featuredListing -> ").Append(featuredListing.ToString());
                logText = logText.Append("active -> ").Append(active.ToString());
                logText = logText.Append(" )");

                // Write the log into handled exception list
                ILog log = LogHelper.GetHandledFileLogger("Product");
                if (log.IsErrorEnabled)
                    log.Error(logText.ToString(), ex);

                throw ex;
            }
        }

        public static Product CreateProduct(string name, string name2, string description, string tempImageFolder,
            string categoryId, string brandId, string displayOrder, string price, double currentCost,double additionalPrice,string additionalPriceDesc, string recipies,string additionalinfo,
            double standardCost, bool isSpecial, string itemNumber,
            bool featuredListing, bool active, List<ProductStock> stocks)
        {
            try
            {
                name = Security.BindStringInput(name, SecurityLevel.Zero);
                name2 = Security.BindStringInput(name2, SecurityLevel.Zero);
                description = Security.BindStringInput(description, SecurityLevel.Zero);
                tempImageFolder = Security.BindStringInput(tempImageFolder, SecurityLevel.Zero);
                categoryId = Security.BindStringInput(categoryId, SecurityLevel.Zero);
                brandId = Security.BindStringInput(brandId, SecurityLevel.Zero);
                displayOrder = Security.BindStringInput(displayOrder, SecurityLevel.Zero);
                price = Security.BindStringInput(price, SecurityLevel.Zero);
                itemNumber = Security.BindStringInput(itemNumber, SecurityLevel.Zero);

                recipies = Security.BindStringInput(recipies, SecurityLevel.Zero);
                additionalinfo = Security.BindStringInput(additionalinfo, SecurityLevel.Zero);


                if (TblProductExtended.CountItemNumber(itemNumber) > 0)
                    throw new DuplicateException(AutoGearCommonMessage.DuplicateProductItemNumber);

                int categoryIdValue = int.Parse(categoryId);
                int brandIdValue = int.Parse(brandId);
                double priceValue = double.Parse(price);

                Category category = CategoryManager.Load(categoryIdValue);
                if (category.SubCategoryCount > 0)
                    throw new InvalidOperationException(AutoGearCommonMessage.InvalidCategoryForProductAddition);

                int productId = TblProduct.CreateNewTblProduct(name, name2, description, string.Empty,
                     displayOrder, 0, string.Empty, Convert.ToDecimal(priceValue),
                     Convert.ToDecimal(priceValue), Convert.ToDecimal(priceValue),Convert.ToDecimal(additionalPrice),additionalPriceDesc,recipies,additionalinfo, DateTime.Now, itemNumber,
                     featuredListing, false, false, active, false, false, brandIdValue, categoryIdValue,
                     Convert.ToDecimal(currentCost), Convert.ToDecimal(standardCost), isSpecial);

                foreach (ProductStock stock in stocks)
                {
                    stock.ProductId = productId;
                    ProductStock.Create(stock);
                }

                Product newProduct = new Product(productId, name, name2, description, string.Empty, displayOrder, 0, priceValue,
                     priceValue,additionalPrice,additionalPriceDesc,recipies,additionalinfo, DateTime.Now, itemNumber, featuredListing, false, false, active, false, false,
                     string.Empty, priceValue, currentCost, standardCost, isSpecial, ManufacturerManager.GetById(brandIdValue), category, stocks);

                try
                {
                    newProduct = ProductFileAccessUtility.CreateProductFiles(newProduct, tempImageFolder);
                }
                catch (Exception ex)
                {
                    TblProduct.DeleteTblProduct(newProduct.ProductId);
                    throw ex;
                }
                TblProduct.UpdateTblProduct(newProduct.ProductId, newProduct.ProductName,newProduct.ProductName2, newProduct.ProductDescription,
                    newProduct.ProductImageUrl, newProduct.DisplayOrder, newProduct.VisitCount, newProduct.ProductUrl,
                    Convert.ToDecimal(newProduct.ProductActualPrice), Convert.ToDecimal(newProduct.OldPrice), Convert.ToDecimal(newProduct.RetailPrice),Convert.ToDecimal(newProduct.AdditionalPrice),newProduct.AdditionalPriceDesc,newProduct.Recipies,newProduct.AdditionalInfo, newProduct.CreateDate,
                    newProduct.ItemNumber, newProduct.IsFeatured, newProduct.IsFreeShipping, newProduct.IsNewArrival,
                    newProduct.IsActive, newProduct.IsDeleted, newProduct.IsClearenceItem, newProduct.Brand.ProductBrandId,
                    newProduct.Category.CategoryId, Convert.ToDecimal(currentCost), Convert.ToDecimal(standardCost), isSpecial);


                return newProduct;
            }
            catch (Exception ex)
            {
                // Setting log information about the exception
                StringBuilder logText = new StringBuilder("Create caused server error: Parameters( ");
                logText = logText.Append("name -> ").Append(name);
                logText = logText.Append("description -> ").Append(description);
                logText = logText.Append("tempImageFolder -> ").Append(tempImageFolder);
                logText = logText.Append("categoryId -> ").Append(categoryId);
                logText = logText.Append("brandId -> ").Append(brandId);
                logText = logText.Append("displayOrder -> ").Append(displayOrder);
                logText = logText.Append("price -> ").Append(price);
                logText = logText.Append("itemNumber -> ").Append(itemNumber);
                logText = logText.Append("featuredListing -> ").Append(featuredListing.ToString());
                logText = logText.Append("active -> ").Append(active.ToString());
                logText = logText.Append(" )");

                // Write the log into handled exception list
                ILog log = LogHelper.GetHandledFileLogger("Product");
                if (log.IsErrorEnabled)
                    log.Error(logText.ToString(), ex);

                throw ex;
            }
        }

        public static int GetBackEndProductListBySearchCount(string productName, int categoryId, bool includeDeleted)
        {
            productName = Security.BindStringInput(productName, SecurityLevel.Zero);

            int count = TblProductExtended.GetBackEndProductListCount(productName, categoryId, includeDeleted);

            return count;
        }
        public static int GetBackEndProductListBySearchCountAdmin(string productName, string itemNumber, int categoryId, bool includeDeleted)
        {
            productName = Security.BindStringInput(productName, SecurityLevel.Zero);
            itemNumber = Security.BindStringInput(itemNumber, SecurityLevel.Zero);
            int count = TblProductExtended.GetBackEndProductListCountAdmin(productName, itemNumber, categoryId, includeDeleted);

            return count;
        }

        public static ReadWriteCustomCollection<Product> GetBackEndProductListBySearch(string productName, int categoryId,
            bool includeDeleted, string sortBy, int firstItem, int pageSize)
        {
            productName = Security.BindStringInput(productName, SecurityLevel.Zero);
            sortBy = Security.BindStringInput(sortBy, SecurityLevel.Zero);

            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetBackEndProductList(productName, categoryId, includeDeleted, sortBy, firstItem, pageSize);

            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> GetBackEndProductListBySearchAdmin(string productName, string itemNumber ,int categoryId,
          bool includeDeleted, string sortBy, int firstItem, int pageSize)
        {
            productName = Security.BindStringInput(productName, SecurityLevel.Zero);
            itemNumber = Security.BindStringInput(itemNumber, SecurityLevel.Zero);
            sortBy = Security.BindStringInput(sortBy, SecurityLevel.Zero);

            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetBackEndProductListAdmin(productName,itemNumber ,categoryId, includeDeleted, sortBy, firstItem, pageSize);

            return LoadFromCustomCollection(productData);
        }

        public static void DeleteProducts(List<int> idList)
        {
           TblProduct.DeleteTblProductList(idList);
        }

        public static void DeleteProducts(ReadWriteCustomCollection<Product> products)
        {
            List<int> deleteIds = new List<int>();

            foreach (Product product in products)
            {
                ProductFileAccessUtility.DeleteProductFiles(product);
                deleteIds.Add(product.ProductId);
            }
            TblProduct.DeleteTblProductList(deleteIds);
            //TblProductExtended.TemporaryDeleteProducts(deleteIds);
        }

      

        public static Product ChangeImageFile(string imageTempFile, Product product)
        {
            if (ProductFileAccessUtility.DeleteProductImage(product))
                return ProductFileAccessUtility.ChangeImages(product, imageTempFile);
            else
                return null;
        }

        public Product Update()
        {
            Product newProduct;

            if (IsProductNameChanged)
            {
                Product oldProduct = Load(this.ProductId);
                newProduct = ProductFileAccessUtility.UpdateProductFiles(oldProduct, this);
            }
            else
                newProduct = this;

            TblProduct productData = new TblProduct(newProduct.ProductId,
                newProduct.ProductName, newProduct._productName2, newProduct.ProductDescription, newProduct.ProductImageUrl,
                newProduct.DisplayOrder, 0, newProduct.ProductUrl, Convert.ToDecimal(newProduct.ProductActualPrice),
                Convert.ToDecimal(newProduct.OldPrice), Convert.ToDecimal(newProduct.RetailPrice),Convert.ToDecimal(newProduct.AdditionalPrice),newProduct.AdditionalPriceDesc, newProduct.Recipies,newProduct.AdditionalInfo,
                newProduct.CreateDate, newProduct.ItemNumber, newProduct.IsFeatured,
                newProduct.IsFreeShipping, newProduct.IsNewArrival, newProduct.IsActive, newProduct.IsDeleted,
                newProduct.IsClearenceItem, 0, newProduct.Category.CategoryId,
                Convert.ToDecimal(newProduct.CurrentCost), Convert.ToDecimal(newProduct.StandardCost), newProduct.IsSpecial);

            productData.Save();

            if (newProduct.Stocks.Count > 0)
            {
                newProduct.Stocks[0].Update();
            }
            return newProduct;
        }


        public static Product ChangeCategory(Product product, Category productCategory)
        {
            Product newProduct = new Product(product.ProductId, product.ProductName, product.ProductName2, product.ProductDescription,
                product.ProductImageUrl, product.DisplayOrder, product.VisitCount, product.OldPrice, product.RetailPrice,product.AdditionalPrice,product.AdditionalPriceDesc,product.Recipies,product.AdditionalInfo,
                product.CreateDate, product.ItemNumber, product.IsFeatured, product.IsFreeShipping, product.IsNewArrival,
                product.IsActive, product.IsDeleted, product.IsClearenceItem, product.ProductUrl,
                product.ProductActualPrice, product.CurrentCost, product.StandardCost, product.IsSpecial, product.Brand, productCategory, product.Stocks);

            return ProductFileAccessUtility.UpdateProductFiles(product, newProduct);
        }

        public static Product GetProductByItemNumber(string itemNumber)
        {
            itemNumber = Security.BindStringInput(itemNumber, SecurityLevel.Zero);

            TblProduct productData = TblProductExtended.GetProductByItemNumber(itemNumber);
            return new Product(productData);
        }

        public static List<string> GetAutoCompleteItemNumberData(string prefixText, int count)
        {
            List<string> itemList = new List<string>();
            ECommerce.DAL.CustomCollection<TblProduct> productData = TblProductExtended.GetNonDeletedProductsByItemNumberPrefix(prefixText, count);
            ReadWriteCustomCollection<Product> products = LoadFromCustomCollection(productData);
            foreach (Product product in products)
            {
                itemList.Add("'" + product.ItemNumber + "'");
            }
            return itemList;
        }

        public static ReadWriteCustomCollection<Product> GetProductListExcludedFavorites(bool indcludeDeleted)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;
            if (indcludeDeleted)
                productData = TblProductExtended.GetProductListForFavorites();
            else
                productData = TblProductExtended.GetNonDeletedProductListForFavorites();

            return LoadFromCustomCollection(productData);
        }

        public static ReadWriteCustomCollection<Product> GetProductListSpecials()
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;
            productData = TblProductExtended.GetProductListSpecials();
            return LoadFromCustomCollection(productData);
        }

        public static void RemoveFavoriteProducts(ReadWriteCustomCollection<Product> products)
        {
            List<int> updateIds = new List<int>();
            foreach (Product product in products)
            {
                updateIds.Add(product.ProductId);
            }
            TblProductExtended.RemoveFavorites(updateIds);
        }

        public static void AddToFeturedItem(Product product)
        {
            product.IsFeatured = true;
            product.Update();
        }

        public static void UpdateDisplayOrder(ReadWriteCustomCollection<KeyValuePair<int, int>> displayOrders)
        {
            ////ReadWriteCustomCollection<Product> products = Product.GetBackEndProductListBySearch("", 0, false, "CONVERT(int,DisplayOrder)", 0, 99999);
            //ReadWriteCustomCollection<Product> products = Product.Products(0, 99999, DataState.NonDeleted);
            //int[] displayOrderToProductId = new int[products.Count];
            //int[] productIdToDisplayOrder = new int[products.Count];
            //int[] displayOrderCount = new int[products.Count];

            //foreach (Product product in products)
            //{
            //    int index = int.Parse(product.DisplayOrder);
            //    displayOrderCount[index]++;
            //}

            //for (int i = 0; i < displayOrders.Count; i++) {
            //    int index = int.Parse(product.DisplayOrder);
            //    array[index]++;                           
            //}
        }

        public static ReadWriteCustomCollection<Product> GetBackendProductPurchaseProductListBySoldDate(DateTime fromdate, DateTime todate)
        {
            ECommerce.DAL.CustomCollection<TblProduct> tblProductPurchaseOrder = TblProductExtended.GetBackendProductPurchaseProductListBySoldDate(fromdate, todate);
            return LoadFromCustomCollection(tblProductPurchaseOrder);
        }

        public static ReadWriteCustomCollection<Product> GetProductByCategoryURL(string catName)
        {
            ECommerce.DAL.CustomCollection<TblProduct> productData = null;
            if(catName!=null)
                productData = TblProductExtended.GetProductByCategoryURL(catName);

            return LoadFromCustomCollection(productData);
        }
       
    }
}
